extends KinematicBody2D

signal playSound()
signal offScreen()
signal onScreen()

const UP = Vector2(0, -1)
const WALK_MAX_SPEED = 100
const RUN_MAX_SPEED = 200
const ACCELERATION = 4
const TERMINAL_VELOCITY = 480

var state = "big"
var gravity = 20
var motion = Vector2()
var inputDirection = 0
var inputDown
var inputJump
var jumpAccel
var inputRun
var maxSpeed = WALK_MAX_SPEED
var _interactable_object


func _ready():
	set_process_input(true)
	update_state()
	

func _input(event):
	if Input.is_action_pressed("move_right"):
		inputDirection = 1
	if Input.is_action_pressed("move_left"):
		inputDirection = -1
	if event.is_action_pressed("move_down"):
		inputDown = 1
	if not Input.is_action_pressed("move_down"):
		inputDown = 0
	if not Input.is_action_pressed("move_left") and not Input.is_action_pressed("move_right"):
		inputDirection = 0
	if event.is_action_pressed("move_run"):
		inputRun = 1
		run()
	elif Input.is_action_just_released("move_run"):
		inputRun = 0
		run_release()
	if event.is_action_pressed("move_jump"):
		inputJump = 1
		if is_on_floor():
			jump()
	elif Input.is_action_just_released("move_jump"):
		inputJump = 0
		jump_cut()
	pass
	
func _physics_process(_delta):
	
	var friction = true
	
	if not is_on_floor():
		$big.playing = false
		$small.playing = false
		friction = false
		emit_signal("playSound", "jump")
	
	motion.y += gravity
	
	if inputDirection != 0:
		if is_on_floor() && abs(motion.x+(ACCELERATION*inputDirection)) <= maxSpeed:
			if inputDown:
				inputDirection = 0
				inputJump = 0
			motion.x = motion.x+(inputDirection*ACCELERATION)
		if not is_on_floor() && abs(motion.x+(ACCELERATION*inputDirection)) <= WALK_MAX_SPEED or abs(motion.x+(ACCELERATION*inputDirection)) < abs(motion.x):
			motion.x = motion.x+(inputDirection*ACCELERATION)
		if is_on_floor() && abs(motion.x) > maxSpeed: #Player should be able to jump without losing speed if they only press one button at a time.
			motion.x = lerp(motion.x, maxSpeed, .05)
			
		#Accelerate faster when moving backwards
		if $big.is_flipped_h() && inputDirection < motion.x or not $big.is_flipped_h() && inputDirection > motion.x:
			if abs(motion.x+(ACCELERATION*inputDirection)) <= maxSpeed:
				motion.x += 2*inputDirection
		
		if abs(motion.x) >= WALK_MAX_SPEED && not inputDown:
			$RunCollision.disabled = false
		else:
			$RunCollision.disabled = true #Player can run over single tile wide gaps
			
		
	if abs(motion.x) <= inputDirection && friction or inputDirection == 0 && friction or inputDown && friction:
		friction()
			
	if is_on_floor() && motion.y >= gravity: #Prevent jump animation playing after a player lands
		inputJump = 0
		
	if inputDown && is_on_floor() && state == "big": #Set the player collision to be smaller when crouching and change the animation
		if abs(motion.x) > WALK_MAX_SPEED:
			if !$big.is_flipped_h() && motion.x > 0 or $big.is_flipped_h() && motion.x < 0: #Don't roll backwards
				$big.animation = "roll"
		elif $big.animation != "roll":
			$big.animation = "crouch"
		$CollisionShape2D.disabled = true
		$CollisionShape2D2.disabled = false
	elif not inputDown && is_on_floor() && state == "big":
		$CollisionShape2D.disabled = false
		$CollisionShape2D2.disabled = true
		
	if is_on_floor() && not motion.x == 0 && not inputJump && not inputDown: #Set the walking animation
		if $big.is_flipped_h() && -1 < motion.x or !$big.is_flipped_h() && 1 > motion.x:
			$big.animation = "skid"
			$small.animation = "skid"
			
			if abs(motion.x) > WALK_MAX_SPEED/2:
				$sfx/skid.playing = true
				emit_signal("playSound", "skid")
		else:
			walk_animation()
		if inputDirection == 1:
			$big.flip_h = 0
			$small.flip_h = 0
		elif inputDirection == -1:
			$big.flip_h = 1
			$small.flip_h = 1
	else:
		$big.playing = true
		$small.playing = true

	if position.x > 2048:
		position.x = 0
		
	if position.y > 32:
		position.y = -256
		
	if position.y < -200:
		emit_signal("offScreen")
	else:
		emit_signal("onScreen")
	
	if motion.y > TERMINAL_VELOCITY:
		motion.y = TERMINAL_VELOCITY
	pass
	motion = move_and_slide(motion, UP)
func jump():
	jumpAccel = -420
	if abs(motion.x) >= WALK_MAX_SPEED:
		jumpAccel = -420-(abs(motion.x)/4)
	motion.y += jumpAccel
	$big.animation = "jump"
	$small.animation = "jump"
	$big.playing = true
	$small.playing = true
	$sfx/jump.playing = true
	emit_signal("playSound", "jump")
	pass
func jump_cut():
	if motion.y < -80:
		motion.y = lerp(motion.y, -80, .4)
	pass
func run():
	maxSpeed = RUN_MAX_SPEED
	
func run_release():
	maxSpeed = WALK_MAX_SPEED
	
func unstuck():
	motion.x += 20
func walk_animation():
	if abs(motion.x) < 10:
		$big.playing = true
		$big.animation = "idle"
		$small.playing = true
		$small.animation = "idle"
	elif abs(motion.x) > WALK_MAX_SPEED:
		$big.animation = "run"
		$small.animation = "run"
	else:
		$big.animation = "walk"
		$small.animation = "walk"
func friction():
	motion.x = lerp(motion.x, 0, .08)
	walk_animation()
	if abs(motion.x) < 8:
		motion.x = 0

func update_state():
	if state == "small":
		$small.visible = true
		$big.visible = false
		$CollisionShape2D.disabled = true
		$CollisionShape2D2.disabled = false
	if state == "big":
		$small.visible = false
		$big.visible = true
		$CollisionShape2D.disabled = false
		$CollisionShape2D2.disabled = true
		
func _on_Area2D_body_entered(body): #figure out later how to give springboard the interact method
	if body.has_method("interact"):
		_interactable_object = body
